package server;

import java.io.*;
import java.net.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/* ChatserverServer, der Verbindungsanfragen entgegennimmt 
 * 
 * Der Server erhält als Parameter zum erstellen den Port auf welchem er lauschen soll.
 * Der Server nimmt Verbindungsanfragen auf diesem Port anschließend entgegen und 
 * erzeugt einen UserHandler-Thread, welcher die Verbindung bearbeitet.
 * 
 * Da das Protokoll darauf beruht, dass jeder Client auf dem gleichen UDP-Port
 * lauscht(50000), machen mehrere Verbindungen vom gleichen Host keinen Sinn und
 * werden direkt abgewiesen.
 * 
 * Der Server verwaltet außerdem die angemeldeten Benutzer in einer Liste von User-Objekten.
 * Diese Liste ist für den Zugriff synchronisiert, da mehrere Threads auf ihr arbeiten.
 */ 
 public class Server extends Thread {
	private final int SERVER_PORT;
        private List<User> userList = Collections.synchronizedList(new ArrayList<User>());
	
        /** Konstruktor für den Server
         * @param port der Port auf welchem gelauscht werden soll
         */
        public Server(int port) {
            SERVER_PORT = port;
        }
        
     @Override
        public void run() {
            ServerSocket serverSocket;  // TCP-Server-Socketklasse
            Socket clientSocket;     // TCP-Standard-Socketklasse

            try {
                serverSocket = new ServerSocket(SERVER_PORT);
                System.out.println("RN Chatserver gestartet auf TCP-Port  " + SERVER_PORT);
                //Connection loop
                while (true) {
                    clientSocket = serverSocket.accept();
                    if (containsHostname(clientSocket.getInetAddress().getHostName()))
                        clientSocket.close(); //Mehrere Verbindungen von einem Host machen bei diesem Protokoll keinen Sinn
                    else
                        (new UserHandler(clientSocket, this)).start();
                }
            } catch (IOException e) {
                System.err.println(e.toString());
                System.err.println("Server is shutting down");
            }
	}
        
        /**
         * Benutzer am Server anmelden
         * @param u der Benutzer, der angemeldet werden soll
         * @return u der Benutzer
         */
        public User addUser(User u) {
            userList.add(u);
            return u;
        }
        
        /**
         * @return eine Kopie der Liste mit Benutzern, die angemeldet sind
         */
        public List<User> userList() {
            return new ArrayList<>(userList);
        }
        
        /**
         * Den übergebenen User aus der Liste der angemeldeten User entfernen.
         * @param u der Benutzer, welcher entfernt wird.
         */
        public void removeUser(User u) {
            userList.remove(u);
        }
        
        /**
         * Prüft, ob der Benutzername bereits vergeben ist. 
         * @param name der Name, nach welchen gesucht werden soll.
         * @return true, wenn der Name vergeben ist, ansonsten false
         */
        public boolean containsUser(String name) {
            for(User u : userList)
                if (u.username.equals(name))
                    return true;
            return false;
        }
        
        /**
         * Prüft, ob ein Hostname bereits verwendet wird.
         * @param hostname der Hostname, der gesucht werden soll
         * @return true, wenn er vergeben ist, ansonsten false
         */
        public boolean containsHostname(String hostname) {
            for (User u : userList)
                if (u.hostname.equals(hostname))
                    return true;
            return false;
        }
}